/**
 * @author Alex Tan
 */
package com.jhws.common.base.controller;

import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jhws.sys.user.bo.OnlineUser;
import com.jhws.common.*;
import com.jhws.common.base.bo.Global;
import com.jhws.common.base.service.DashBoardService;
import com.jhws.core.shiro.execption.secLevelAccountEmptyException;
import com.jhws.core.shiro.session.RedisSessionDao;
import com.jhws.sys.role.service.ITblRoleDimService;
import com.jhws.sys.user.service.ITblUserDimService;
import com.jhws.util.LogHelper;
import com.jhws.util.MailUtil;
import com.jhws.util.StringUtils;
import com.jhws.util.security.CryptionData;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.jhws.sys.role.bo.TblRoleDimBo;
import com.jhws.sys.user.bo.TblUserDimBo;
import com.jhws.common.base.bo.JsonRespData;
import com.jhws.sys.user.bo.TblUserDimForm;

@Controller
@RequestMapping("/LoginCtrl")
public class LoginCtrl {
    @Resource
    ITblUserDimService IUserService;
    @Resource
    ITblRoleDimService IRoleService;
    @Resource
    RedisSessionDao sessionDAO;
    @Resource
    RedisTemplate stringTemplate;
    @Resource
    DashBoardService dashBoardService;

    @RequestMapping("login.x")
    public String showLoginForm(HttpServletRequest req, Model model) {

        Session session = SecurityUtils.getSubject().getSession(false);
        if(session != null &&  session.getAttribute(TblUserDimBo.USER_INFO_REFERENCE) != null){
            return "redirect:/LoginCtrl/loginindex.x";
        }

        String exceptionClassName = (String) req.getAttribute("shiroLoginFailure");
        String error = null;
        if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
            error = "该用户不存在!";
        } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误";
        } else if (AccountException.class.getName().equals(exceptionClassName)) {
            error = "您的账户已被锁定，请联系管理员";
        } else if (ExcessiveAttemptsException.class.getName().equals(exceptionClassName)) {
            error = "连续失败了" + Global.LOGIN_PASSWORD_FAIL_COUNT + "次，您的账户已被锁定，请一小时后再尝试";
        } else if (secLevelAccountEmptyException.class.getName().equals(exceptionClassName)) {
            error = "该账号没有绑定任何小区!,请先分配小区!";
        } else if (exceptionClassName != null) {
            error = "其他错误：" + exceptionClassName;
        } else if (req.getParameter("AuthCodeFailed") != null) {
            error = "验证码错误";
        } else if (req.getParameter("anotherUser") != null){
            error = "您已登录了另一个账号"+req.getParameter("username")+",请退出后再登陆!";
        }
        model.addAttribute("message", error);

        /* 通过属性读出动态主页logo与名称 */
        String loginName = PropertiesReader.getProperty("loginName");
        loginName = loginName.startsWith("$")?null:loginName;

        String loginLogo = PropertiesReader.getProperty("loginLogo");
        loginLogo = loginLogo.startsWith("$")?null:loginLogo;

        model.addAttribute("loginName",loginName);
        model.addAttribute("loginLogo",loginLogo);

        return "login/login";
    }


    @RequestMapping("edit.x")
    public String edit(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return "edit";
    }

    @RequestMapping("anon/verificationCode.x")
    @ResponseBody
    public JsonRespData verificationCode(String username, String email) throws Exception {
        TblUserDimBo user = IUserService.getUserByName(username);
        if (user == null || !user.getEmailAddress().equals(email)) {
            return new JsonRespData("", -1, "邮箱地址不正确!");
        }
        ValueOperations valueOperations = stringTemplate.opsForValue();
        String code = String.valueOf((int) (Math.random() * 1000000));
        valueOperations.set(email, code);
        stringTemplate.expire(email, 30, TimeUnit.MINUTES);
        MailUtil.sendMail(email, code);
        return new JsonRespData("", 1, "");
    }

    @RequestMapping("anon/findPassword.x")
    @ResponseBody
    public JsonRespData findPassword(String username, String email, String verificationCode, String password) throws Exception {
        ValueOperations valueOperations = stringTemplate.opsForValue();
        String code = (String) valueOperations.get(email);
        if (code.equals(verificationCode)) {
            TblUserDimBo user = IUserService.getUserByName(username);
            user.setLogPwd(new CryptionData().EncryptionStringData(password));
            IUserService.save(user);
            return new JsonRespData("", 1, "修改密码成功!");
        }
        return new JsonRespData("", -1, "验证码不正确!");
    }

    @RequestMapping("updatePw.x")
    public String updatePw(TblUserDimForm form,
                           HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        TblUserDimForm userForm = (TblUserDimForm) form;
        TblUserDimBo user = (TblUserDimBo) request.getSession().getAttribute(
                TblUserDimBo.USER_INFO_REFERENCE);

        Calendar cld = Calendar.getInstance();
        cld.add(Calendar.DATE, 30);
        // 设置该用户密码的过期时间为30天后
        // user.setPassTime(format.format(cld.getTime()));
        if (null == user) {
            user = new TblUserDimBo();
            List<TblUserDimBo> userList = IUserService.findTblUserDimByWhere("where log_name = '" + userForm.getLogName() + "'");
            user.setUserCode(userList.get(0).getUserCode());
            user.setLogName(userForm.getLogName());
            user.setUserName(userList.get(0).getUserName());
            user.setLastLogTime(userList.get(0).getLastLogTime());
            user.setEmailAddress(userList.get(0).getEmailAddress());
            user.setRoleCode(userList.get(0).getRoleCode());
            user.setTelNum(userList.get(0).getTelNum());
            user.setUserState(userList.get(0).getUserState());
        }

        if (null != userForm.getConfirmPwd() && !userForm.getConfirmPwd().equals(user.getLogPwd())) {
            user.setLogPwd((new CryptionData()).EncryptionStringData(userForm
                    .getConfirmPwd().trim()));
        }
        IUserService.save(user);
        SysLogger.logInfo(request, "修改用户密码,用户编号：" + user.getUserCode());
        request.setAttribute("message", "修改密码成功，请重新登录！");
        return "login";
    }

    @RequestMapping("changePw.x")
    @ResponseBody
    public JsonRespData changePw(TblUserDimForm form)
            throws Exception {
        TblUserDimForm userForm = (TblUserDimForm) form;
        TblUserDimBo user = IUserService.currentUser();
        String pass = "";
        if (null != userForm.getLogPwd()) {
            pass = (new CryptionData()).EncryptionStringData(userForm
                    .getLogPwd());
        }

        if (!user.getLogPwd().equals(pass)) {
            return new JsonRespData("changePw", -1, "原密码输入有误！");
        } else {

            user.setLogPwd((new CryptionData()).EncryptionStringData(userForm
                    .getConfirmPwd()));
            IUserService.save(user);

            return new JsonRespData("changePw", 1, "密码修改成功！");
        }
    }

    @RequestMapping(value = "/loginindex.x")
    public ModelAndView loginindex() throws Exception {
        TblUserDimBo user = IUserService.currentUser();
        ModelAndView mv = new ModelAndView();
        TblRoleDimBo role = IRoleService.findTblRoleDimById(user.getRoleCode());

        mv.addObject("userLogName", user.getLogName());
        mv.addObject("userName", user.getUserName());
        mv.addObject("roleExp", role.getRoleDisplay());
        mv.addObject("version", PropertiesReader.getProperty("version"));

        List<OnlineUser> list = new ArrayList<>();
        if (SecurityUtils.getSubject().hasRole(Global.ROLE_SUPPER_ADMIN)) {
            Collection<Session> sessions = sessionDAO.getActiveSessions();
            Map onlineUsersMap = new HashMap();
            LogHelper.d("sesstion number : "+sessions.size());
            for (Session session : sessions) {
                Object username = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
                if (username == null)
                    continue;

                if(onlineUsersMap.get(username) == null) {
                    OnlineUser onlineUser = new OnlineUser();
                    onlineUsersMap.put(username, 1);
                    onlineUser.setAccessTime(session.getStartTimestamp().toString());
                    onlineUser.setUsername(username.toString());
                    onlineUser.setIp(session.getHost());

                    list.add(onlineUser);
                }
            }
            mv.addObject("onlineUsers", list);
        }

        mv.addObject("menus",IUserService.getUserMenus(user));

        if (StringUtils.isEmpty(user.getTelNum()))
            mv.addObject("infoLost", true);


        String loginName = PropertiesReader.getProperty("loginName");
        loginName = loginName.startsWith("$")?null:loginName;

        mv.addObject("loginName",loginName);

        mv.setViewName("login/loginindex");
        return mv;
    }

    @RequestMapping("save.x")
    public String save(TblUserDimForm form,
                       HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        TblUserDimForm userForm = (TblUserDimForm) form;
        TblUserDimBo user = (TblUserDimBo) request.getSession().getAttribute(
                TblUserDimBo.USER_INFO_REFERENCE);
        String pass = (new CryptionData()).EncryptionStringData(userForm
                .getLogPwd());
        if (!user.getLogPwd().equals(pass)) {
            request.setAttribute("message", "原密码输入有误，请返回！");
            request.setAttribute("backurl", "/LoginCtrl/edit.x");
            return "/share/commonerror";
        } else {
            // SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
            // Calendar cld = Calendar.getInstance();
            // cld.add(Calendar.DATE, 30);
            // user.setPassTime(format.format(cld.getTime()));//
            // 设置该用户密码的过期时间为30天后
            // user.setLoginPwd(userForm.getConfirmPwd());
            // getUserDimService().resetPassword(user);
            // request.setAttribute("message", "密码修改成功，请重新登录！");
            // request.setAttribute("backurl", "/logout.jsp");
            return "/share/commonsuccess";
        }
    }

    @RequestMapping("resetPassword.x")
    @ResponseBody
    public JsonRespData resetPassword(String userCode) throws Exception {
        TblUserDimBo user = IUserService.findTblUserDimById(userCode);
        if (user != null) {
            user.setLogPwd((new CryptionData()).EncryptionStringData("123456"));
            IUserService.save(user);
            return new JsonRespData("resetPassword", 1, "");
        } else {
            return new JsonRespData("resetPassword", -1, "");
        }
    }

    /**
     * 获取主页仪表盘面板的相关数据
     * @return
     * @throws Exception
     */
    @RequestMapping("getDashBoardInfo.x")
    @ResponseBody
    public JsonRespData getDashBoardInfo() throws Exception{
        Map retMap = new HashMap();
        String commSql = IUserService.getUserCommsSqlStr(IUserService.currentUser());

        retMap.put("units", dashBoardService.getUnitsInfo(commSql));
        retMap.put("owners", dashBoardService.getOwnersInfo(commSql));
        retMap.put("park", dashBoardService.getParkingLots(commSql));

        if(StringUtils.isNotEmpty(commSql)) {
            retMap.put("devs", dashBoardService.getDevsInfo(commSql));
            retMap.put("card", dashBoardService.getICCardInfo(commSql));
            retMap.put("repair", dashBoardService.getNewRepair(commSql));
            retMap.put("propertyArrearage",dashBoardService.getPropertyArrearages(commSql));
        }else{
            retMap.put("feedback",dashBoardService.findFeedbackCount());
            retMap.put("aliPay",dashBoardService.findAliPayApplying());
        }

        return new JsonRespData("", 1, retMap);
    }
}
